#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/module.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/input.h>

/*
note: four key, use for input system.
	EINT0	-->	GPF0
	EINT2	-->	GPF2
	EINT11	-->	GPG3
	EINT19	--> GPG11
*/

typedef struct key_irq_desc{
	int irq;
	int pin;
	int pin_val;
	char *name;
	irqreturn_t (*irq_func)(int irq, void *dev_id);
}KEY_DESC;


struct input_dev *devp;
static struct timer_list key_tmr;
static KEY_DESC *pin_desc;

static irqreturn_t key_irq_func(int irq, void *dev_id)
{
	pin_desc = (KEY_DESC *)dev_id;

	if(!pin_desc){
		return IRQ_RETVAL(IRQ_NONE);
	}

#if 0
	printk("IN: irq = %x \n", irq);
	printk("irq = %d\n", pin_desc->irq);
	printk("pin = %d\n", pin_desc->pin);
	printk("pin_val = %d\n", pin_desc->pin_val);
#endif	
	
	printk("00 : name = %s\n", pin_desc->name);

	mod_timer(&key_tmr, jiffies + HZ/100);
	
	return IRQ_RETVAL(IRQ_HANDLED);
}


static KEY_DESC key_irq_table[]={
	{IRQ_EINT0, S3C2410_GPF(0), S3C2410_GPF0_EINT0,  "eint_0", key_irq_func},
	{IRQ_EINT2, S3C2410_GPF(2), S3C2410_GPF2_EINT2,  "eint_2", key_irq_func},
	//{IRQ_EINT0, S3C2410_GPF(0), S3C2410_GPF0_EINT0, 0, "key_1"},
	//{IRQ_EINT0, S3C2410_GPF(0), S3C2410_GPF0_EINT0, 0, "key_1"},			
};

static void key_tmr_func(unsigned long val)
{
	unsigned int pin_val;
	
	pin_val = s3c2410_gpio_getpin(pin_desc->pin);

	if(pin_val){
		input_event(devp, EV_KEY, pin_desc->pin_val, 1);
		
		input_sync(devp);
		printk("11 : name = %s\n", pin_desc->name);
	}
	else{
		input_event(devp, EV_KEY, pin_desc->pin_val, 0);
		input_sync(devp);
		printk("11 : name = %s\n", pin_desc->name);
	}
}

static int  __init input_key_init(void)
{
	int i, ret;

	for(i=0; i<(sizeof(key_irq_table)/sizeof(key_irq_table[0])); i++){
		ret = request_irq(key_irq_table[i].irq, key_irq_table[i].irq_func, 
			IRQ_TYPE_EDGE_BOTH, key_irq_table[i].name, (void *)&key_irq_table[i]);
	}

	devp = input_allocate_device();

	//devp->name = "input_key";
 	//devp->evbit[0]= BIT_MASK(EV_SYN)|BIT_MASK(EV_KEY);
	//set_bit(KEY_0, );
	set_bit(EV_KEY, devp->evbit);
	devp->name = "input_key";

	input_register_device(devp);

	init_timer(&key_tmr);
	key_tmr.function = key_tmr_func;
	add_timer(&key_tmr);
	
	
	return 0;
}

static void  __exit input_key_exit(void)
{
	int nr;

	for(nr=0; nr<(sizeof(key_irq_table)/sizeof(key_irq_table[0])); nr++){
		free_irq(key_irq_table[nr].irq, (void *)&key_irq_table[nr]);
	}
	
	
}

module_init(input_key_init);
moudle_exit(input_key_exit);


MODULE_LICENSE("GPL");

